#include <mips/regdef.h>
#include <sys/syscall.h>

//////////////// STACK ///////////////////////////////////////////////////
//-------------SRA--------------pos		reg			//
//								44		pad			//
//								40		ra			//
//								36		fp			//
//								32		gp			//
//-------------SRA----------------					//
//-------------LTA----------------					//
//								28		PAD			//
//								24		result		//
//								20		last		//
//								16		actual		//
//-------------LTA----------------					//
//-------------ABA----------------					//
//								12					//
//								8					//
//								4					// #Va a llamar a read que tiene 3 argumentos
//								0					//
//-------------ABA----------------					//
//////////////////////////////////////////////////////////////////////////

# Constantes para hacer mas clara la ABI
#define STACK_SP 48  
#define	STACK_RA 40
#define	STACK_FP 36
#define STACK_GP 32
#define STACK_RESULT 24
#define STACK_LAST 20
#define STACK_ACTUAL 16
#define LA 16  		#Local Area.
#define ABA 0		#Argument Build Area.

#define SYS_read 3 # Codigo de la syscall read

# Variables globales y el tamanio en bytes de cada una
.extern characters, 4
.extern words, 4
.extern lines, 4

	.text
	.align 2
	.globl wc
	.ent wc



wc: 
		.frame $fp,STACK_SP, ra
		.set noreorder
		.cpload t9
		.set reorder

		#Stack Frame.
		subu sp, sp, STACK_SP
		.cprestore STACK_GP
		sw ra, STACK_RA(sp)
		sw $fp, STACK_FP(sp)
		move $fp, sp

		
		sw a0,STACK_SP($fp)    # Guardo mi argumento en la ABA de la funcion padre   
		lw t0,0($fp)	# Cargo mi argumento en registro temporal
		
	
inicializarvariables:
		# Inicializo variables y locales, guardo resultados en la memoria
		li t1, -1
		sw t1, STACK_LAST($fp) 		# last <- -1
		sw zero, STACK_RESULT($fp)	# result <- 0
		sw zero, STACK_ACTUAL($fp)	# actual <- 0
		sw zero, characters		# characters <- 0
		sw zero, lines			# lines <- 0
		sw zero, words 			# words <- 0

while:		
doread:   	#Preparo para la llamada a la funcion syscall READ.
		lw a0,STACK_SP($fp)		# File Descriptor del archivo de entrada
		la a1,STACK_ACTUAL($fp)		# Puntero al buffer (actual)
		li a2,1  			# Tamanio a leer.
read:	 	#Cargo SYS_read
		li v0,SYS_read
		syscall				# Al hacer la syscall me pone en la pos de memoria de actual el caracter leido

		bltz v0, errorread 		#Verifico si hay error, si read me devuelve < 0, hay error
		beqz v0, eof			#Comparo si lei 1 byte, sino es fin de archivo.
		# Si no hay error y no estoy en eof voy a cuenta
docount:
		# Preparo para llamar a count
		lw a0, STACK_ACTUAL($fp)	# Argumento 1 del count: actual 
		lw a1, STACK_LAST($fp)		# Argumento 2 del count: last
		jal count			
		lw t0, STACK_ACTUAL($fp)
		sw t0, STACK_LAST($fp)		# last <- actual
		b while				# Siguiente ciclo del while
errorread:
		li v0,1				# Devuelvo un 1 porque hubo error de lectura
		b fin
eof:
	li v0,0				# Devuelvo 0 porque llegue al eof
fin:	
	move sp,$fp
	lw ra,STACK_RA(sp)	#recupero ra
	lw $fp,STACK_FP(sp)	#recupero fp
	addu sp, sp, STACK_SP
	j ra # vuelvo al programa.

.end wc
